

namespace Nadine{

	class NDW32ReadWriteLocker : public NDReadWriteLocker
	{
	private:
		HANDLE 	m_hRWHandler;
		LONG	m_nISLocked;

	protected:
	public:
		explicit NDW32ReadWriteLocker();
		virtual ~NDW32ReadWriteLocker() { release(); }

		virtual void release();

		virtual void acquireRWLock(UINT nWaitTime =INFINITE);
		virtual void releaseRWLock();

	};

	class NDW32WorkThread :public NDWorkThread
	{
	protected:
		virtual void initRWL()
		{
			this->m_pTD =new NDW32ReadWriteLocker();
			this->m_pFL =new NDW32ReadWriteLocker();
		}
		virtual void releaseRWL()
		{
			delete m_pTD;
			delete m_pFL;
		}

	public:
		explicit NDW32WorkThread( NDArk* pArk, UINT nThreadType ) :NDWorkThread(pArk, nThreadType)	{ initRWL(); }
		virtual ~NDW32WorkThread() { releaseRWL(); }

	};

	class NDW32ThreadPool :public NDThreadPool
	{
	private:
		struct threadArg
		{
			NDW32ThreadPool*	pThis;
			UINT				nThreadNo;
		};

		std::vector<threadArg*> m_myThreadArg;

		//normal thread
		UINT					m_nNumThreads;
		UINT					m_nNumQueue;

		//UINT					m_nTopIndex;
		//UINT					m_nBottomIndex;
		LONG					m_nWorkInProgress;
		LONG					m_nGLWorkInProgress;

		HANDLE					m_hEmptySlot;
		HANDLE					m_hWorkToDo;
		HANDLE					m_hExit;

		HANDLE*					m_threadhandles;
		UINT*					m_threadaddr;

		NDW32ReadWriteLocker*	m_pQRWL;
		NDWorkThread**			m_pQueue;

		//opengl thread
		UINT					m_nGLNumThreads;
		UINT					m_nGLNumQueue;

		UINT					m_nGLTopIndex;
		UINT					m_nGLBottomIndex;
		//LONG					m_nGLWorkInProgress;

		HANDLE					m_hGLEmptySlot;
		HANDLE					m_hGLWorkToDo;
		//HANDLE					m_hGLExit;

		HANDLE*					m_GLthreadhandles;
		UINT*					m_GLthreadaddr;

		NDW32ReadWriteLocker*	m_pGLQRWL;
		NDWorkThread**			m_pGLQueue;

		UINT					m_nExecutedGLTasks;
		UINT					m_nExecutedTasks;

		NDW32ReadWriteLocker*			m_acrtRWL;
		CGrowableArray< NDWorkThread* > m_arrCurrRunningThread;

	protected:
		void threadWork( UINT nThreadNo );
		bool getWork( NDWorkThread** ppNDWT );

		void GLthreadWork( UINT nThreadNo );
		bool getGLWork( NDWorkThread** ppNDWT );

		//NDWorkThread** getQueue();
		//NDWorkThread** getGLQueue();
		//CGrowableArray< NDWorkThread* >* getCWT();

		//thread-safe func.
		void NDW32ThreadPool::addRemoveWork(bool bAdd, Nadine::NDWorkThread* pNDWT );
		void NDW32ThreadPool::getSetQueue(bool bGet, Nadine::NDWorkThread** ppNDWT);
		void NDW32ThreadPool::getSetGLQueue(bool bGet, Nadine::NDWorkThread** ppNDWT);

	public:
		NDW32ThreadPool() :
		  NDThreadPool(), 
		  m_threadhandles(0), 
		  m_threadaddr(0),
		  m_GLthreadhandles(0),
		  m_nExecutedGLTasks(0),
		  m_nExecutedTasks(0),
		  m_GLthreadaddr(0) {}
		virtual ~NDW32ThreadPool()
		{
			assert( m_myThreadArg.empty() ==true );
			
			assert( m_threadhandles ==0 );
			assert( m_threadaddr ==0 );

			assert( m_GLthreadhandles ==0 );
			assert( m_GLthreadaddr ==0 );
		}

		virtual void release();
		virtual bool initialize();
		virtual bool submitJob( NDWorkThread* pNDWT, bool bGLThread, DWORD nWaitTime =50 ); 

		static UINT CALLBACK threadDoWork( void* pParam )
		{
			((threadArg*)pParam)->pThis->threadWork(((threadArg*)pParam)->nThreadNo);
			return 0;
		}

		static UINT CALLBACK threadDoGLWork( void* pParam )
		{
			((threadArg*)pParam)->pThis->GLthreadWork(((threadArg*)pParam)->nThreadNo);
			return 0;
		}
	};

}